package com.onadake.web.domain;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

import com.onadake.utils.ValidationUtils;

/**
 * Describes the chat message object.
 * 
 * @author radek.hecl
 *
 */
public class ChatMessage {

    /**
     * Builder class.
     */
    public static class Builder {
        
        /**
         * Code of the owner of this message.
         */
        private String ownerCode;

        /**
         * Text of the message.
         */
        private String text;

        /**
         * Timestamp in the UTC time zone when message was inserted into the system.
         * Format is yyyy/MM/dd HH:mm:ss.SSS.
         */
        private String utcInsertTimestamp;
        
        /**
         * Sets code of the message owner.
         *  
         * @param ownerCode code of the message owner
         * @return this instance
         */
        public Builder setOwnerCode(String ownerCode) {
            this.ownerCode = ownerCode;
            return this;
        }

        /**
         * Sets text of the message.
         *  
         * @param text text of the message
         * @return this instance
         */
        public Builder setText(String text) {
            this.text = text;
            return this;
        }

        /**
         * Sets timestamp when the message has been inserted in UTC time zone.
         * Format is yyyy/MM/dd HH:mm:ss.SSS.
         *  
         * @param utcInsertTimestamp timestamp when the message has been inserted in UTC time zone
         * @return this instance
         */
        public Builder setUtcInsertTimestamp(String utcInsertTimestamp) {
            this.utcInsertTimestamp = utcInsertTimestamp;
            return this;
        }

        /**
         * Builds the result object.
         * 
         * @return created object
         */
        public ChatMessage build() {
            return new ChatMessage(this);
        }
    }

    /**
     * Code of the owner of this message.
     */
    private String ownerCode;

    /**
     * Text of the message.
     */
    private String text;

    /**
     * Timestamp in the UTC time zone when message was inserted into the system.
     * Format is yyyy/MM/dd HH:mm:ss.SSS.
     */
    private String utcInsertTimestamp;

    /**
     * Creates new instance.
     * 
     * @param builder builder object
     */
    public ChatMessage(Builder builder) {
        ownerCode = builder.ownerCode;
        text = builder.text;
        utcInsertTimestamp = builder.utcInsertTimestamp;
        guardInvariants();
    }

    /**
     * Guards this object to be consistent. Throws exception if this is not the case.
     */
    private void guardInvariants() {
        ValidationUtils.guardMatch(ownerCode, "^US[0-9A-Z]{13}$", "owner code must match ^US[0-9A-Z]{13}$");
        ValidationUtils.guardNotNull(text, "text cannot be null");
        ValidationUtils.guardMatch(utcInsertTimestamp, "[0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\\.[0-9]{3}",
                "utcInsertTimestamp must match [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\\.[0-9]{3}");
    }
    
    /**
     * Returns code of the owner of this message.
     * 
     * @return code of the owner of this message
     */
    public String getOwnerCode() {
        return ownerCode;
    }
    
    /**
     * Returns text of this message.
     * 
     * @return text of this message
     */
    public String getText() {
        return text;
    }
    
    /**
     * Returns UTC timestamp when this message was inserted.
     * Format is yyyy/MM/dd HH:mm:dd.SSS.
     * 
     * @return UTC timestamp when this message was inserted
     */
    public String getUtcInsertTimestamp() {
        return utcInsertTimestamp;
    }
    
    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
    
}
